package com.syh.jn.scm.infrastructure.wrapper;

import cn.redscarf.commons.util.other.ExtStringUtils;
import cn.redscarf.commons.wrapper.Wrapper;
import cn.redscarf.commons.wrapper.expression.conditionExpression.*;
import cn.redscarf.commons.wrapper.expression.support.Expression;
import cn.redscarf.commons.wrapper.expression.support.SimpleExpression;
import com.google.common.base.CaseFormat;
import com.syh.core.BaseCore;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;


public class ResolveToSQL extends BaseResolve implements BaseCore {

  public ResolveToSQL(Wrapper wrapper) {
    super(wrapper);
  }

  public ResolveToSQL(Wrapper wrapper, ParseMethods parseMethods) {
    super(wrapper, parseMethods);
  }


  protected StringBuffer parseCondition(Expression criterion) {

    StringBuffer sb = new StringBuffer();

    if (criterion instanceof Between) {
      Between expression = (Between) criterion;
      sb.append(String.format("%s BETWEEN %s AND %s",
              this.parsePropertyName(expression.propertyName),
              new StringBuilder().append(typeTran(expression.low)).toString(),
              new StringBuilder().append(typeTran(expression.high)).toString()
      ));
    }

    if (criterion instanceof In) {
      In expression = (In) criterion;

      List list = Arrays.asList(expression.values).stream().map((item) -> {
        return new StringBuilder().append("'").append(item).append("'").toString();
      }).collect(Collectors.toList());
      String valuesString = String.join(",", list);

      sb.append(String.format("%s IN (%s)", this.parsePropertyName(expression.propertyName), valuesString));

    }
    if (criterion instanceof NotIn) {
      NotIn expression = (NotIn) criterion;

      List list = Arrays.asList(expression.values).stream().map((item) -> {
        return item.toString();
      }).collect(Collectors.toList());
      String valuesString = String.join(",", list);

      sb.append(String.format("%s NOT IN (%s)", this.parsePropertyName(expression.propertyName), valuesString));

    }
    if (criterion instanceof Like) {
      Like expression = (Like) criterion;
      sb.append(String.format("%s LIKE %s", this.parsePropertyName(expression.propertyName), new StringBuilder().append(typeTran(expression.value)).toString(), "'"));

    }
    if (criterion instanceof IsNull) {
      IsNull expression = (IsNull) criterion;
      sb.append(String.format("%s IS NULL", this.parsePropertyName(expression.propertyName)));
    }
    if (
            criterion instanceof NotNull) {
      NotNull expression = (NotNull) criterion;
      sb.append(String.format("%s IS NOT NULL", this.parsePropertyName(expression.propertyName)));
    }
    // 6
    if (
            criterion instanceof PropertyExpression) {
      PropertyExpression expression = (PropertyExpression) criterion;
      sb.append(String.format("%s %s %s", this.parsePropertyName(expression.propertyName), expression.op, this.parsePropertyName(expression.otherPropertyName)));
    }
    // 7
    if (criterion instanceof SimpleExpression) {
      SimpleExpression expression = (SimpleExpression) criterion;
      sb.append(String.format("%s %s %s", this.parsePropertyName(expression.propertyName), expression.op, new StringBuilder().append(typeTran(expression.value)).toString()));

    }

    return sb;
  }

  @Override
  protected String parsePropertyName(String propertyName) {
    String innerPropertyName = null;
    if (this.parseMethods != null) {
      innerPropertyName = this.parseMethods.customParsePropertyName(propertyName);
    }

    if (ExtStringUtils.isEmpty(innerPropertyName)) {
      innerPropertyName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, propertyName);
    }

    return innerPropertyName;
  }

  private String typeTran(Object val) {
    if (val instanceof Number) {
      return val.toString();
    }
    return ExtStringUtils.buildString("'", val==null?"":val.toString(), "'");
  }
}
